import { isArray } from 'util'
import { exportDefault, titleCase } from '@/views/workflow/utils/generator/index'
import { trigger } from './config'
import enums from '@/views/workflow/utils/enum'

const units = {
  KB: '1024',
  MB: '1024 / 1024',
  GB: '1024 / 1024 / 1024'
}
let confGlobal
const inheritAttrs = {
  file: '',
  dialog: 'inheritAttrs: true,'
}

export function makeUpJs(conf, type) {
  confGlobal = conf = JSON.parse(JSON.stringify(conf))
  const dataList = []
  const ruleList = []
  const optionsList = []
  const propsList = []
  const methodList = mixinMethod(conf, type)
  const uploadVarList = []
  const mounteds = []

  /* 
    表单中某些字段的值和数据源（如下拉列表）是需要通过sql或者js动态获取的（即设置字段的值类型valueData），
    而其中又有首次加载后不改变和随着其他字段的值改变两种情况，
    第一种要在页面加载的时候获取，第二张需要监听每个字段值的变化，所以valueData
  */
  const watchList = [] // 字段监控函数列表
  const valueDataList = [] // 根据其他字段获取valueData的语句列表
  const valueDataByFieldList = [] // 初始化获取valueData的语句列表

  
  const tableData = [] // 绑定表格组件的列的数据（如列为下拉框，则需要绑定下拉框的数据源）

  conf.fields.forEach(el => {
    buildAttributes(el, 
      dataList, 
      ruleList, 
      optionsList, 
      methodList, 
      propsList, 
      uploadVarList, 
      mounteds, 
      conf, 
      watchList, 
      valueDataList, 
      valueDataByFieldList, 
      tableData
    )
  })
  const script = buildexport(
    conf,
    type,
    dataList.join('\n'),
    ruleList.join('\n'),
    optionsList.join('\n'),
    uploadVarList.join('\n'),
    propsList.join('\n'),
    methodList.join('\n'),
    mounteds.join('\n'),
    watchList.join('\n'),
    valueDataList.join('\n'),
    valueDataByFieldList.join('\n'),
    tableData.join('\n')

  )
  confGlobal = null
  return script
}

function buildAttributes(el, 
  dataList, 
  ruleList, 
  optionsList, 
  methodList, 
  propsList, 
  uploadVarList, 
  mounteds, 
  conf, 
  watchList, 
  valueDataList, 
  valueDataByFieldList,
  tableData
) {
  buildData(el, dataList)
  buildRules(el, ruleList)
  if (el.tag === 'quill-editor') {
    mounteds.push(`
      if (this.$refs.${el.vModel}QuillEditor) {
        // 为图片ICON绑定事件  getModule 为编辑器的内部属性
        this.$refs.${el.vModel}QuillEditor.quill.getModule('toolbar').addHandler('image', this.${el.vModel}ImgHandler)
      }`
    )
    buildEditorImgUploadMethod(el, methodList)
    // if (el.options) {
    //   buildOptions(el, optionsList)
    //   buildBlurMethod(el, methodList)
    // }
    buildBlurMethod(el, methodList)
  }

  // if (el.options && el.options.length) {
  if (['el-checkbox-group', 'el-radio-group', 'el-select'].indexOf(el.tag) > -1) {
    buildOptions(el, optionsList)
    if (el.tag === 'el-select') {
      buildOptionChange(el, conf, methodList) // 为每个标签添加选中事件
    }
    if (el.dataType === 'dynamic') {
      const model = `${el.vModel}Options`
      const options = titleCase(model)
      buildOptionMethod(`get${options}`, model, methodList)
    }
  }

  if (el.props && el.props.props) {
    buildProps(el, propsList)
  }

  if (el.tag === 'el-upload') {
    uploadVarList.push(
      // `${el.vModel}Action: '${el.action}',
      `${el.vModel}fileList: [],`
    )
    methodList.push(buildBeforeUpload(el))
    methodList.push(buildUploadWatch(el, conf, watchList))
    methodList.push(buildHttpRequest(el, conf))
    methodList.push(buildUploadChange(el, conf))
    // if (!el['auto-upload']) {
    //   methodList.push(buildSubmitUpload(el))
    // }
  }
  if (el.tag === 'el-table') {
    methodList.push(buildTableEvent(el, conf))
    buildTableData(el, conf, 
      valueDataList, 
      valueDataByFieldList, 
      tableData
    )
  }
  if (el.tabs) {
    el.tabs.forEach(tab => {
      if (tab.children) {
        tab.children.forEach(el2 => {
          buildAttributes(el2, 
            dataList, 
            ruleList, 
            optionsList, 
            methodList, 
            propsList, 
            uploadVarList, 
            mounteds, 
            conf, 
            watchList, 
            valueDataList, 
            valueDataByFieldList, 
            tableData
          )
        })
      }
    })
  }
  if (el.children) {
    el.children.forEach(el2 => {
      buildAttributes(el2, 
        dataList, 
        ruleList, 
        optionsList, 
        methodList, 
        propsList, 
        uploadVarList, 
        mounteds, 
        conf, 
        watchList, 
        valueDataList, 
        valueDataByFieldList, 
        tableData
      )
    })
  }

  // for (let i = 0; i < arguments.length; i++) {
  //   // console.log(arguments[i])
  // }
  if (el.sysType) { // 系统组件
    methodList.push(buildSysComponentsMethods(el, conf))
  }
  // 设置监听formData的变化，并获取valueData
  getFormFieldWatch(conf, el, watchList)
  // 设置formData获取valueData
  getFormFieldValueDataList(conf, el, valueDataList, valueDataByFieldList)
}

function buildSysComponentsMethods(el, conf) {
  let methodStr = ''
  if (el.sysType) { // 选择型组件需要添加回调函数
    if (['user-link', 'supplier-link', ].indexOf(el.tag) >= 0 ) {
      let vName = `''`
      if (el.tag === 'user-link') {
        vName = 'data.name'
      }
      methodStr = `
        ${el.vModel}callbackInfo(data) {
          this.${conf.formModel}['${el.vName}'] = ${vName}
        },
      `
    } 
    // else if (el.tag === 'dept-position-user') {
    //   methodStr = `
    //     ${el.vModel}valueChange(value) {
    //       this.${conf.formModel}['${el.vModel}'] = value
    //       ${el.vModel1 ? `this.${conf.formModel}['${el.vModel1}'] = value.deptId || ''` : ''}
    //       ${el.vName1 ? `this.${conf.formModel}['${el.vName1}'] = value.deptName || ''` : ''}
    //       ${el.vModel2 ? `this.${conf.formModel}['${el.vModel2}'] = value.positionId || ''` : ''}
    //       ${el.vName2 ? `this.${conf.formModel}['${el.vName2}'] = value.positionName || ''` : ''}
    //       ${el.vModel3 ? `this.${conf.formModel}['${el.vModel3}'] = value.value || ''` : ''}
    //       ${el.vName3 ? `this.${conf.formModel}['${el.vName3}'] = value.userName || ''` : ''}
    //     },
    //   `
    // } 
    else if (['dept-select', 'dept-position-s', 'dept-user-s'].indexOf(el.tag) >= 0) {
      // if (el.multiple) { // 多选
        methodStr = `
          ${el.vModel}valueChange(value, valueDetail) {
            this.${conf.formModel}['${el.vModel}'] = value
            let vName = []
            let vModel1 = []
            let vName1 = []
            let vModel2 = []
            let vName2 = []
            if (valueDetail && valueDetail.length) {
              valueDetail.forEach(item => {
                vName.push(item.label)
                vModel1.push(item.id.split('-')[0])
                vName1.push(item.parentLabel)
                if (item.id.split('-').length === 2) {
                  vModel2.push(item.id.split('-')[1])
                  if (item.customLabel) {
                    vName2.push(item.customLabel.split('-')[1])
                  } else {
                    vName2.push(item.label.split('-')[1])
                  }
                }
              })`
            methodStr += `
            }`
            
            if (el.vName) {
              // if(this.${conf.formModel}.hasOwnProperty('${el.vName}')) {
              //   this.${conf.formModel}['${el.vName}'] = vName.join(',')
              // }
              methodStr += 
              `
                this.${conf.formModel}['${el.vName}'] = vName.join(',')
              `
            }
            if (el.vModel1) {
              methodStr += 
              `
                this.${conf.formModel}['${el.vModel1}'] = vModel1.join(',')
              `
            }
            if (el.vName1) {
              methodStr += 
              `
                this.${conf.formModel}['${el.vName1}'] = vName1.join(',')
              `
            }
            if (el.vModel2) {
              methodStr += 
              `
                this.${conf.formModel}['${el.vModel2}'] = vModel2.join(',')
              `
            }
            if (el.vName2) {
              methodStr += `
                this.${conf.formModel}['${el.vName2}'] = vName2.join(',')
              `
            }
            methodStr += `
          },
        `
      // } else { // 单选
      //   if (el.tag === 'dept-select') {
      //     methodStr = `
      //       ${el.vModel}select(node) {
      //         debugger
      //         const id = ''
      //         const name = ''
      //         if (node) {
      //           id = node.id || ''
      //           ${el.vName ? `name = node.label || ''` : ''}
      //         }
      //         this.${conf.formModel}['${el.vModel}'] = id
      //         ${el.vName ? `this.${conf.formModel}['${el.vName}'] = name` : '' }
      //       },
      //     `
      //   } else {
      //     methodStr = `
      //       ${el.vModel}select(node) {
      //         const model = ''
      //         const model1 = ''
      //         const name1 = ''
      //         const model2 = ''
      //         const name2 = ''
      //         if (node) {
      //           model = node.id || ''
      //           ${el.vModel1 ? `model1 = node.id.split('-')[0] || ''` : ''}
      //           ${el.vName1 ? `name1 = node.parentLabel || ''` : ''}
      //           ${el.vModel2 ? `model2 = node.id.split('-')[1] || ''` : ''}
      //           ${el.vName2 ? `name2 = node.label.replace('-' + node.parentLabel, '') || ''` : ''}
      //         }
      //         this.${conf.formModel}['${el.vModel}'] = model
      //         ${el.vModel1 ? `this.${conf.formModel}['${el.vModel1}'] = model1` : ''}
      //         ${el.vName1 ? `this.${conf.formModel}['${el.vName1}'] = name1` : ''}
      //         ${el.vModel2 ? `this.${conf.formModel}['${el.vModel2}'] = model2` : ''}
      //         ${el.vName2 ? `this.${conf.formModel}['${el.vName2}'] = name2` : ''}
      //       },
      //     `
      //   }
      // }
    }
  }
  return methodStr
}

function mixinMethod(conf, type) {
  const list = []
  const minxins = {
    file: confGlobal.formBtns ? {
      submitForm: `submitForm() {
      this.$refs['${confGlobal.formRef}'].validate(async valid => {
        if(!valid) {
          this.$message.error('请填写或选择页面上的必填项')
          return
        }
        // TODO 提交表单
        this.btnSubmitLoading = true
        // await this.handleSubmit(this.${conf.formModel}, this.auditStatus, this.comment)
        // this.btnSubmitLoading = false
        try {
          await this.handleSubmit(this.${conf.formModel}, this.auditStatus, this.comment, this.relayUser)
        }
        catch(err) {

        }
        finally {
          this.btnSubmitLoading = false
        }
      })
    },
    callbackTabDataSelected(fieldName, rows, callback) { // 选择行回调
      if (fieldName && rows) {
        callback(fieldName, rows)
      }
    },
    `,
      resetForm: `resetForm() { // 表单清空
      this.$refs['${confGlobal.formRef}'].resetFields()
    },`
    } : null,
    dialog: {
      onOpen: 'onOpen() {},',
      onClose: `onClose() {
      this.$refs['${confGlobal.formRef}'].resetFields()
    },`,
      close: `close() {
      this.$emit('update:visible', false)
    },`,
      handelConfirm: `handelConfirm() {
      this.$refs['${confGlobal.formRef}'].validate(valid => {
        if(!valid) return
        this.close()
      })
    },`
    }
  }

  const methods = minxins[type]
  if (methods) {
    Object.keys(methods).forEach(key => {
      list.push(methods[key])
    })
  }

  return list
}

function buildData(conf, dataList) {
  if (conf.vModel === undefined)  {
    if (conf.tag === 'el-table') { // 数据来源为SQL查询
      dataList.push(`'table${conf.formId}': [],`)
    }
    return
  }
  let defaultValue
  if (typeof (conf.defaultValue) === 'string' && !conf.multiple) {
    defaultValue = `'${conf.defaultValue}'`
  } else {
    defaultValue = `${JSON.stringify(conf.defaultValue)}`
  }
  if (conf.tag === 'el-table') {
    defaultValue = '[]'
  }
  dataList.push(`'${conf.vModel}': ${defaultValue},`)
}

function buildRules(conf, ruleList) {
  if (conf.vModel === undefined && !conf.componentName) return
  const rules = []
  if (trigger[conf.tag]) {
    if (conf.required) {
      const type = isArray(conf.defaultValue) ? 'type: \'array\',' : ''
      let message = isArray(conf.defaultValue) ? `请至少选择一个${conf.label}` : conf.placeholder
      if (message === undefined) message = `${conf.label}不能为空`
      rules.push(`{ required: true, ${type} message: '${message}', trigger: '${trigger[conf.tag]}' }`)
    }
    if (conf.regList && isArray(conf.regList)) {
      conf.regList.forEach(item => {
        if (item.pattern) {
          rules.push(`{ pattern: ${eval(item.pattern)}, message: '${item.message}', trigger: '${trigger[conf.tag]}' }`)
        }
      })
    }
    ruleList.push(`${conf.vModel}: [${rules.join(',')}],`)
  } else {
    if (conf.tag === 'el-table') { // 表格内部组件的验证
      if (conf.columns && conf.columns.length) {
        const propsRules = {}
        conf.columns.forEach(item => {
          if (Object.keys(enums.TAB_COLUMN_TTYPE)[2] === item.type) {
            const el = item.component
            if (el.required) {
              const type = isArray(el.defaultValue) ? 'array' : undefined
              let message = isArray(el.defaultValue) ? `请至少选择一个${el.label}` : el.placeholder
              if (message === undefined) message = `${el.label}不能为空`
              propsRules[item.prop]= [{ required: true, type: type, message: message, trigger: trigger[el.tag] }]
            }
          }
        })
        ruleList.push(`'${conf.componentName}': JSON.parse('${JSON.stringify(propsRules)}'),`)
      }
    }
  }
}

function buildOptions(conf, optionsList) {
  conf.options = conf.options || []
  if (conf.vModel === undefined) return
  if (conf.dataType === 'dynamic') { conf.options = [] }
  const str = `${conf.vModel}Options: ${JSON.stringify(conf.options)},`
  optionsList.push(str)
}

function buildProps(conf, propsList) {
  if (conf.dataType === 'dynamic') {
    conf.valueKey !== 'value' && (conf.props.props.value = conf.valueKey)
    conf.labelKey !== 'label' && (conf.props.props.label = conf.labelKey)
    conf.childrenKey !== 'children' && (conf.props.props.children = conf.childrenKey)
  }
  const str = `${conf.vModel}Props: ${JSON.stringify(conf.props.props)},`
  propsList.push(str)
}

function buildBeforeUpload(conf) {
  const unitNum = units[conf.sizeUnit]; let rightSizeCode = ''; let acceptCode = ''; const
    returnList = []
  if (conf.fileSize) {
    rightSizeCode = `let isRightSize = file.size / ${unitNum} < ${conf.fileSize}
    if(!isRightSize){
      this.$message.error('文件大小超过 ${conf.fileSize}${conf.sizeUnit}')
    }`
    returnList.push('isRightSize')
  }
  if (conf.accept) {
    acceptCode = `let isAccept = new RegExp('${conf.accept}').test(file.type)
    if(!isAccept){
      this.$message.error('应该选择${conf.accept}类型的文件')
    }`
    returnList.push('isAccept')
  }
  const str = `${conf.vModel}BeforeUpload(file) {
    ${rightSizeCode}
    ${acceptCode}
    return ${returnList.join('&&')}
  },`
  return returnList.length ? str : ''
}

function buildUploadWatch(el, conf, watchList) {
  const str = `'uploadfileList.${el.vModel}fileList': {
    handler(n, o) {
      if (n && n.length) {
        this.${conf.formModel}['${el.vModel}'] = n.map(item => {
          return item.uploadId
        }).join(',')
      } else {
        this.${conf.formModel}['${el.vModel}'] = ''
      }
    },
    deep: true
  },
  `
  watchList.push(str)
}
function buildHttpRequest(el, conf) {
  const str = `async ${el.vModel}HttpRequest(info) {
    const res = await this.saveOnlyUploads(info)
    if(res.state === '000000' || res.data) {
      const url = res.data.fileUrl + res.data.fileName
      const index = this.uploadfileList['${el.vModel}fileList'] ? this.uploadfileList['${el.vModel}fileList'].length : 0
      const file = {
        index: index,
        name: res.data.fileName,
        uploadId: res.data.uploadId,
        url: url
      }
      this.uploadfileList['${el.vModel}fileList'].push(file)
    }
  },`
  return str
}
function buildUploadChange(el, conf) {
  const str = `${el.vModel}Change(file, fileList) {
    
  },`
  return str
}

function buildSubmitUpload(conf) {
  const str = `submitUpload() {
    this.$refs['${conf.vModel}'].submit()
  },`
  return str
}

function buildBlurMethod(el, methodList) {
  const methodName = `${el.vModel}Blur`
  const str = `${methodName}() {
    this.$refs['${confGlobal.formRef}'].validateField('${el.vModel}')
  },`
  methodList.push(str)
}

// 构建富文本图片上传方法
function buildEditorImgUploadMethod(el, methodList) {
  const methodTrigger = `${el.vModel}ImgHandler` // 触发el-upload的上传
  const methodSuccess = `${el.vModel}ImgUpScuccess` // el-upload上传成功的回调函数
  const str = `${methodTrigger}(state) {
    this.addRange = this.$refs.${el.vModel}QuillEditor.quill.getSelection()
    if (state) {
      let fileInput = document.getElementById('${el.vModel}UploadTrigger')
      fileInput.click() // 加一个触发事件
    }
  },
  async ${methodSuccess}(info) {// 图片上传成功回调   插入到编辑器中
    const res = await this.saveOnlyUploads(info)
    console.log(res) // 上传接口返回的数据
    if(res.state !== '000000' || !res.data) {
      this.$message.error(res.message || '图片插入失败')
      return
    }
    let vm = this
    const url = res.data.fileUrl + res.data.fileName // 获得文件上传后的URL地址
    if (url != null && url.length > 0) { // 将文件上传后的URL地址插入到编辑器文本中
      let value = url
      // API: https://segmentfault.com/q/1010000008951906
      // this.$refs.myTextEditor.quillEditor.getSelection();
      // 获取光标位置对象，里面有两个属性，一个是index 还有 一个length，这里要用range.index，即当前光标之前的内容长度，然后再利用 insertEmbed(length, 'image', imageUrl)，插入图片即可。
      vm.addRange = vm.$refs.${el.vModel}QuillEditor.quill.getSelection()
      // value = value.indexOf('http') !== -1 ? value : 'http://' + value
      const uploadType = 'image'
      vm.$refs.${el.vModel}QuillEditor.quill.insertEmbed(vm.addRange !== null ? vm.addRange.index : 0, uploadType, value) // 调用编辑器的 insertEmbed 方法，插入URL
    } else {
      this.$message.error('图片插入失败')
    }
    this.$refs['${el.vModel}Upload'].clearFiles() // 插入成功后清除input的内容
  },
  `
  methodList.push(str)
}

// 构建表格相关事件
function buildTableEvent(el, conf) {
  const fieldName = el.vModel || `table${el.formId}`
  // valueData如果是SQL(即字符串)，需要对立面的单引号和换行做转译处理
  const valueData = el.valueData ? el.valueData.replace(/[']/g, '\\\'').replace(/[\r\n]/g, ' ') : el.valueData
  const columns = JSON.parse(JSON.stringify(el.columns))
  let defaultRow = {}
  columns.forEach(item => {
    if (item.prop) {
      let empty = null
      if (item.component && item.component.tag == 'el-input-number') {
        empty = undefined
      }
      defaultRow[item.prop] = item.defaultValue || empty
    }
    item.component = undefined
  })

  let maxRowCondition = ''
  if (el.maxRows) { // 允许添加的最大行数
    maxRowCondition = `
      if (${el.maxRows} && ${el.maxRows} > 0 && (this.${conf.formModel}[fieldName].length >= ${el.maxRows} || ((rows && rows.length + this.${conf.formModel}[fieldName].length) > ${el.maxRows}))) {
        this.$message.error('最多只能添加 [${el.maxRows}] 行')
        return
      }
    `
  }
  const str = `
  handle${el.componentName}Select() { // 选择行
    this.$refs.TabDataSelector.show('${fieldName}', '${JSON.stringify(columns)}', '${el.valueType}', '${valueData}', this.formData, this.${conf.formModel}['${fieldName}'], this.handle${el.componentName}Add)
  },
  handle${el.componentName}Add(fieldName = '${fieldName}', rows) { // 添加行
    const data = this.${conf.formModel}[fieldName] || []
    this.$set(this.${conf.formModel}, fieldName, data)
    ${maxRowCondition}
    if (rows && rows.length) {
      this.${conf.formModel}[fieldName] = this.${conf.formModel}[fieldName].concat(rows)
    } else {
      this.${conf.formModel}[fieldName].push(JSON.parse('${JSON.stringify(defaultRow)}'))
    }
  },
  handle${el.componentName}Remove(row, index) { // 删除行
    this.${conf.formModel}['${fieldName}'].splice(index, 1)
  },
  handle${el.componentName}CurrentChange(val) { // 单选
    
  },
  handle${el.componentName}SelectionChange(val) { // 多选
    
  },
  init${el.componentName}ColumnsData() {
    ${buildTableColumnsData}
  },
  `
  return str
}

function buildTableColumnsData(el, conf) {
  return ''
  // if (el.columns && el.columns.length) {
  //   el.columns.forEach(element => {
  //     if (el.editable && Object.keys(enums.TAB_COLUMN_TTYPE)[2] === element.type && element.tag) { // 可编辑，且该列为组件列，则渲染组件
  //       if (element.tag === 'el-select') {
  //         let options = element.component.options
  //         `${el.componentName}[${element.prop}Options]` = options
  //       }
  //     }
  //   })
  // }
}

// 构建表格内部子组件的数据绑定
function buildTableData(
  el, 
  conf,
  valueDataList, 
  valueDataByFieldList, 
  tableData
) {
  let obj = {}
  if (el.columns && el.columns.length) {
    el.columns.forEach(element => {
      if (el.editable && Object.keys(enums.TAB_COLUMN_TTYPE)[2] === element.type && element.tag) { // 可编辑，且该列为组件列，则渲染组件
        if (element.component) {
          if (element.tag === 'el-select') {
            let options = element.component.options
            obj[`${element.prop}Options`] = options // 静态数据绑定
          }
          // 动态数据绑定
          element.component.table = {
            tableName: el.componentName,
            prop: element.prop
          }
          getFormFieldValueDataList(conf, element.component, valueDataList, valueDataByFieldList)
        }
      }
    })
  }
  const field = `
    ${el.componentName}: ${JSON.stringify(obj)},
  `
  tableData.push(field)
}

function buildOptionChange(el, conf, methodList) {
  const str = `${el.vModel}Change(val) {
    if (${el.vName}) {
      if (Array.isArray(val)) {
        const names = []
        val.forEach(item => {
          const obj = this.${el.vModel}Options.find(opt => opt.value == item)
          if (obj) {
            names.push(obj.label)
          }
        })
      } else {
        const obj = this.${el.vModel}Options.find(opt => opt.value == val)
        names.push(obj.label)
      }
      this.$set(this.${conf.formModel}, '${el.vName}', names.join(','))
    }
  },`
  methodList.push(str)
}

function buildOptionMethod(methodName, model, methodList) {
  const str = `${methodName}() {
    // TODO 发起请求获取数据
    this.${model}
  },`
  methodList.push(str)
}

function getFormFieldWatch(conf, el, watchList) { // 添加属性值的监听函数
  const watchFun = `
  '${conf.formModel}.${el.vModel}': function(n, o) {
    if (n !== o) {
      this.getValueDataByField('${el.vModel}')
    }
  },`
  watchList.push(watchFun)
}

function getFormFieldValueDataList(conf, el, valueDataList, valueDataByFieldList) { // 添加属性值的值数据
  let valueData = getValueData(conf, el)
  let optionValueData = getOptionValueData(conf, el)
  if (el.valueDataColumn && el.valueDataColumn.length) {
    valueData = `
      if ('${el.valueDataColumn.join()}'.split(',').indexOf(field) >= 0) {
        ${valueData}
      }
    `
    // 初始化后不改变的字段放入valueDataByFieldList
    valueDataByFieldList.push(valueData) 
  } else {
    // 随其他字段的值改变的字段放入valueDataList
    valueDataList.push(valueData)
  }

  if (el.optionValueDataColumn && el.optionValueDataColumn.length) {
    optionValueData = `
      if ('${el.optionValueDataColumn.join()}'.split(',').indexOf(field) >= 0) {
        ${optionValueData}
      }
    `
    // 初始化后不改变的字段放入valueDataByFieldList
    valueDataByFieldList.push(optionValueData) 
  } else {
    // 随其他字段的值改变的字段放入valueDataList
    valueDataList.push(optionValueData)
  }
}

function getValueData(conf, el) { // 获取每个字段的valueData
  if (el.tag === 'el-table') return ''
  let fieldName = el.tag === 'el-table' ? el.vModel || `table${el.formId}` : el.vModel
  if (el.table) { // table有值说明是明细表的列组件
    fieldName = `${el.table.tableName}.${el.table.prop}`
  }
  const valueType = el.valueType
  let valueData = el.valueData
  let str = ''
  if (valueType) { // 如果设置了值类型并有关联字段，改变字段的值
    valueData = valueData.replace(/[\r\n]/g, ' ')
    switch(valueType) {
      case Object.keys(enums.VALUE_TYPE)[1]: case Object.keys(enums.VALUE_TYPE)[2]: case Object.keys(enums.VALUE_TYPE)[6]: // SQL、SQL_LIST、SQL_MAP_LIST
        // valueData如果是SQL(即字符串)，需要对里面的单引号和换行做转译处理
        valueData = valueData.replace(/[']/g, '\\\'').replace(/[\r\n]/g, ' ')
        str += `
            this.calculateSQLValue('${fieldName}', '${valueType}', '${valueData}')
          \n
        `
        break
      case Object.keys(enums.VALUE_TYPE)[3]: // DICTIONARIES
        break
      case Object.keys(enums.VALUE_TYPE)[4]: // JAVASCRIPT_MATH
      if (el.table) {
        str += `
            this['${el.table.tableName}']['${el.table.prop}'] = ${valueData}
          \n
        `
      } else {
        // valueData如果是SQL(即字符串)，需要对里面的单引号和换行做转译处理
        valueData = valueData.replace(/[']/g, '\\\'').replace(/[\r\n]/g, ' ')
        str += `
          this.setJsValueData('${el.tag}', ${el.multiple}, '${fieldName}', '${el.valueDataType}', '${valueType}', '${valueData}')
          \n
        `
      }
        break
      case Object.keys(enums.VALUE_TYPE)[5]: // JAVA_MATH
        break
      default:
        break
    }
  }
  return str
}

function getOptionValueData(conf, el) { // 获取每个字段的optionValueData
  let str = ''
  let fieldName = el.tag === 'el-table' ? el.vModel || `table${el.formId}` : el.vModel
  if (el.table) { // table有值说明是明细表的列组件
    fieldName = `${el.table.tableName}.${el.table.prop}`
  }
  const tag = el.tag
  const optionValueType = el.optionValueType
  let optionValueData = el.optionValueData
  if (optionValueType) { // 如果设置了值类型并有关联字段，改变字段的数据源
    switch(optionValueType) {
      case Object.keys(enums.VALUE_TYPE)[1]: // SQL
        break
      case Object.keys(enums.VALUE_TYPE)[2]: case Object.keys(enums.VALUE_TYPE)[3]: case Object.keys(enums.VALUE_TYPE)[6]: // SQL_LIST、DICTIONARIES、SQL_MAP_LIST(用于表格组件绑定初始化数据)
      // optionValueData如果是SQL(即字符串)，需要对立面的单引号和换行做转译处理
      optionValueData = optionValueData.replace(/[']/g, '\\\'').replace(/[\r\n]/g, ' ')  
      str += `
          this.calculateOption('${tag}', '${fieldName}', '${optionValueType}', '${optionValueData}')
          \n
        `
        break
      case 'JAVASCRIPT_MATH': // JAVASCRIPT_MATH
        break
      case Object.keys(enums.VALUE_TYPE)[5]: // JAVA_MATH
        break
      default:
        break
    }
  }
  return str
}

function buildGetValueDataMethods(conf, valueDataList, valueDataByFieldList) {  // 获取valueData的方法

  const methods = `
    getValueData() {
      ${valueDataList}
    },
    getValueDataByField(field) {
      ${valueDataByFieldList}
    },
    async calculateOption(tag, field, valueType, valueData) { // 根据选项值类型获取选项的数据源
      if (!valueType || !valueData) return
      const data = await this.getCalculateValue(valueType, valueData, this.${conf.formModel})
      if (tag === 'el-table') {
        this.${conf.formModel}[field] = data
      } else {
        let options = []
        if (data && data.length) {
          data.forEach(item => {
            if(item) {
              item.label = item.value
              item.value = item.key
              options.push(item)
            }
          })
        }
        if (field.split('.').length > 1) { // 表格组件点击选择行
          const table = field.split('.')[0]
          const prop = field.split('.')[1]
          this[table][prop + 'Options'] = options
        } else {
          this[field + 'Options'] = options
        }
      }
    },
    async calculateSQLValue(field, valueType, valueData) { // 根据字段值类型获取字段的值
      if (!valueType || !valueData) return
      const data = await this.getCalculateValue(valueType, valueData)
      if (['${Object.keys(enums.VALUE_TYPE)[1]}', '${Object.keys(enums.VALUE_TYPE)[6]}'].indexOf(valueType) >= 0) { // SQL、SQL_MAP_LIST
        this.${conf.formModel}[field] = data
      } else if (valueType === '${Object.keys(enums.VALUE_TYPE)[2]}') { // SQL_LIST
        let value = []
        if (data && data.length) {
          data.forEach(item => {
            if(item) {
              value.push(item.key)
            }
          })
        }
        // 数组转换成字符串（如查看附件组件）
        this.${conf.formModel}[field] = value.join(',')
      }
    },
  `
  return methods
}

function buildexport(conf, 
  type, 
  data, 
  rules, 
  selectOptions, 
  uploadVar, 
  props, 
  methods, 
  mounteds, 
  watchList, 
  valueDataList, 
  valueDataByFieldList,
  tableData
) {
  methods += buildGetValueDataMethods(conf, valueDataList, valueDataByFieldList)
  const str = `
  ${exportDefault}{
  ${inheritAttrs[type]}
  components: {},
  data: { // 以对象的形式保存，在渲染的时候再改成函数
      ${conf.formModel}: {
        ${data}
      },
      ${conf.formRules}: {
        ${rules}
      },
      uploadfileList: {
        ${uploadVar}
      },
      ${selectOptions}
      ${props}
      ${tableData}
  },
  computed: {},
  watch: {
    ${watchList}
  },
  mounted: function() {
    ${mounteds}
    this.getValueData()
  },
  methods: {
    ${methods}
  }
}`
  return str
}
